#ifndef __UM_SOURCE_H__
#define __UM_SOURCE_H__

#include "um_basic_types.h"
#include "umapi_os.h"
#include "umapi_libc.h"
#include "umapi_os_list.h"
#include "libavformat/avformat.h"
#include "libavformat/avio.h"
#include "libavformat/version.h"
#include "libavcodec/avcodec.h"
#include "libavutil/avstring.h"


typedef UM_S32 (*sendBuff)(UM_VOID *pSource,AVPacket *pkt);
typedef struct
{
	const UM_CHAR* protocol;
	const UM_CHAR* describe;
	UM_CHAR sourceUrl[256];
	UM_VOID * (*open)(UM_VOID *pSource,UM_CHAR *inUrl);
	UM_VOID * (*open2)(UM_VOID *pSource,UM_VOID **pSendCall);
	UM_S32 (*addSink)(UM_VOID *pSource, UM_VOID *pSink);
	UM_S32 (*delSink)(UM_VOID *pSource, UM_VOID *pSink);
	UM_S32 (*start)(UM_VOID *pSource);
	UM_S32 (*stop)(UM_VOID *pSource);
	UM_S32 (*destroy)(UM_VOID *pSource);
	UM_VOID (*trace)(UM_VOID *pSource);
	AVFormatContext *(*getAvIn)(UM_VOID *pSource);
	UM_S32 priSize;
	UM_VOID *pri;
}S_SOURCE;

#define GETCONTEXT(t, p) (t)(((S_SOURCE *)p)->pri)

#define BASICSOURCEFUN(s_s,i_s,d_s)  \
static UM_S32 addSink(UM_VOID *pSource, UM_VOID *pSink) \
{ \
	s_s *p = GETCONTEXT(s_s *, pSource); \
	S_SINK *s = (S_SINK*)pSink; \
	umapi_os_mutex_lock(p->mutexHandle, -1); \
	umapi_list_add(&((S_SINK *)pSink)->head, &p->sinks); \
	umapi_os_mutex_unlock(p->mutexHandle); \
	return UM_SUCCESS; \
} \
static UM_S32 delSink(UM_VOID *pSource, UM_VOID *pSink) \
{ \
	s_s *p = GETCONTEXT(s_s *, pSource); \
	umapi_os_mutex_lock(p->mutexHandle, -1); \
	umapi_list_del(&((S_SINK *)pSink)->head); \
	umapi_os_mutex_unlock(p->mutexHandle); \
	return UM_SUCCESS; \
} \
static UM_S32 start(UM_VOID *pSource) \
{ \
	s_s *p = GETCONTEXT(s_s *, pSource); \
	umapi_os_mutex_lock(p->mutexHandle, -1); \
	struct umapi_list_head *pos, *n; \
	umapi_list_for_each_safe(pos, n,&p->sinks) \
	{ \
		S_SINK *sink = umapi_list_entry(pos,S_SINK, head); \
		if(sink->start) \
			sink->start(sink); \
	}\
	umapi_os_mutex_unlock(p->mutexHandle); \
	return UM_SUCCESS; \
} \
static UM_S32 trace(UM_VOID *pSource) \
{ \
	s_s *p = GETCONTEXT(s_s *, pSource); \
	umapi_os_mutex_lock(p->mutexHandle, -1); \
	struct umapi_list_head *pos, *n; \
	umapi_list_for_each_safe(pos, n,&p->sinks) \
	{ \
		S_SINK *sink = umapi_list_entry(pos,S_SINK, head); \
		if(sink->trace) \
			sink->trace(sink); \
	}\
	umapi_os_mutex_unlock(p->mutexHandle); \
	return UM_SUCCESS; \
} \
static UM_S32 stop(UM_VOID *pSource) \
{ \
	s_s *p = GETCONTEXT(s_s *, pSource); \
	umapi_os_mutex_lock(p->mutexHandle, -1); \
	struct umapi_list_head *pos, *n; \
	umapi_list_for_each_safe(pos, n,&p->sinks) \
	{ \
		S_SINK *sink = umapi_list_entry(pos,S_SINK, head); \
		if(sink->stop) \
			sink->stop(sink); \
	} \
	umapi_os_mutex_unlock(p->mutexHandle); \
	return UM_SUCCESS; \
}\
static UM_S32 open2(UM_VOID *pSource,UM_VOID **pSendCall) \
{ \
	s_s *p = GETCONTEXT(s_s *, pSource); \
	if(i_s(p, pSource))	\
		return UM_FAILURE; \
	else\
	{\
		*pSendCall = sendDataToSinks; \
		LOGI("pSource:%p, callFun:%p, %p",pSource, *pSendCall, sendDataToSinks); \
		return UM_SUCCESS; \
	}\
}\
static UM_S32 open(UM_VOID *pSource, UM_CHAR *inUrl) \
{ \
	s_s *p = GETCONTEXT(s_s *, pSource); \
	i_s(p, pSource); \
	return UM_SUCCESS; \
}\
static UM_S32 destroy(UM_VOID *pSource) \
{ \
	s_s *p = GETCONTEXT(s_s *, pSource); \
	d_s(p); \
	umapi_os_mutex_lock(p->mutexHandle, -1);	\
	struct umapi_list_head *pos, *n; \
	umapi_list_for_each_safe(pos, n, &p->sinks) \
	{ \
		S_SINK *sink = umapi_list_entry(pos,S_SINK, head); \
		umapi_list_del(&sink->head); \
		if(sink->destroy) \
			sink->destroy(sink); \
		umapi_free(sink); \
	} \
	umapi_os_mutex_unlock(p->mutexHandle);	\
	umapi_os_mutex_destroy(p->mutexHandle); \
	umapi_free(p);\
	return UM_SUCCESS;\
}



extern S_SOURCE streamSource;
extern S_SOURCE avSource;
extern S_SOURCE pkSource;

#endif
